package exporter

import (
	"emc_vnx_exporter/utils"
	"github.com/prometheus/client_golang/prometheus"
	"io/ioutil"
	"log"
	"os/exec"
	"strings"
	"time"
)

type Disk struct {
	Name                   string
	VendorId               string
	ProductId              string
	ProductRevision        string
	Lun                    string
	Type                   string
	State                  string
	HotSpare               string
	PrctRebuilt            string
	PrctBound              string
	SerialNumber           string
	Sectors                string
	Capacity               string
	Private                string
	BindSignature          string
	HardReadErrors         string
	HardWriteErrors        string
	SoftReadErrors         string
	SoftWriteErrors        string
	ReadRetries            string
	WriteRetries           string
	RemappedSectors        string
	NumberOfReads          string
	NumberOfWrites         string
	NumberOfLuns           string
	RaidGroupID            string
	ClariionPartNumber     string
	RequestServiceTime     string
	ReadRequests           string
	WriteRequests          string
	KbytesRead             string
	KbytesWritten          string
	StripeBoundaryCrossing string
	DriveType              string
	ClariionTLAPartNumber  string
	UserCapacity           string
	IdleTicks              string
	BusyTicks              string
	CurrentSpeed           string
	MaximumSpeed           string
}

var (
	disk = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "vnx_get_all_disk",
			Help: "Get All Disk Info",
		},
		[]string{
			"name",
			"VendorId",
			"ProductId",
			"ProductRevision",
			"Lun",
			"Type",
			"State",
			"HotSpare",
			"PrctRebuilt",
			"PrctBound",
			"SerialNumber",
			"Sectors",
			"Capacity",
			"Private",
			"BindSignature",
			"HardReadErrors",
			"HardWriteErrors",
			"SoftReadErrors",
			"SoftWriteErrors",
			"ReadRetries",
			"WriteRetries",
			"RemappedSectors",
			"NumberOfReads",
			"NumberOfWrites",
			"NumberOfLuns",
			"RaidGroupID",
			"ClariionPartNumber",
			"RequestServiceTime",
			"ReadRequests",
			"WriteRequests",
			"KbytesRead",
			"KbytesWritten",
			"StripeBoundaryCrossing",
			"DriveType",
			"ClariionTLAPartNumber",
			"UserCapacity",
			"IdleTicks",
			"BusyTicks",
			"CurrentSpeed",
			"MaximumSpeed",
		},
	)
)

func DiskGauge() *prometheus.GaugeVec {
	return disk
}

func GetDiskMetrics(spIp string, user string, password string) {
	for {
		cmd := exec.Command("bash", "-c", "/opt/Navisphere/bin/naviseccli -h "+spIp+" -user "+user+" -password "+password+" -Scope 0 getdisk")
		stdout, _ := cmd.StdoutPipe()
		defer stdout.Close()
		if err := cmd.Start(); err != nil {
			log.Fatalf("cmd.Start: %v", err)
		}
		result, _ := ioutil.ReadAll(stdout) // 读取输出结果
		resData := string(result)

		diskList := strings.Split(resData, "\n\n")
		for _, diskString := range diskList {
			diskItems := strings.Split(diskString, "\n")
			data := new(Disk)
			for index, diskItem := range diskItems {
				if diskItem == "" {
					continue
				}
				value := diskItem
				if index != 0 {
					value = diskItem[strings.Index(diskItem, ":")+1 : strings.Count(diskItem, "")-1]
					value = strings.Replace(value, "  ", "", -1)
				}
				if index == 0 {
					data.Name = value
				}
				if strings.Contains(diskItem, "Vendor Id") {
					data.VendorId = value
				} else if strings.Contains(diskItem, "Product Id") {
					data.ProductId = value
				} else if strings.Contains(diskItem, "Product Revision") {
					data.ProductRevision = value
				} else if strings.Contains(diskItem, "Lun") {
					data.Lun = value
				} else if strings.Contains(diskItem, "Type") {
					data.Type = value
				} else if strings.Contains(diskItem, "State") {
					data.State = value
				} else if strings.Contains(diskItem, "Hot Spare") {
					data.HotSpare = value
				} else if strings.Contains(diskItem, "Prct Rebuilt") {
					data.PrctRebuilt = value
				} else if strings.Contains(diskItem, "Prct Bound") {
					data.PrctBound = value
				} else if strings.Contains(diskItem, "Serial Number") {
					data.SerialNumber = value
				} else if strings.Contains(diskItem, "Sectors") {
					data.Sectors = value
				} else if strings.Contains(diskItem, "Capacity") {
					data.Capacity = value
				} else if strings.Contains(diskItem, "Private") {
					data.Private = value
				} else if strings.Contains(diskItem, "Bind Signature") {
					data.BindSignature = value
				} else if strings.Contains(diskItem, "Hard Read Errors") {
					data.HardReadErrors = value
				} else if strings.Contains(diskItem, "Hard Write Errors") {
					data.HardWriteErrors = value
				} else if strings.Contains(diskItem, "Soft Read Errors") {
					data.SoftReadErrors = value
				} else if strings.Contains(diskItem, "Soft Write Errors") {
					data.SoftWriteErrors = value
				} else if strings.Contains(diskItem, "Read Retries") {
					data.ReadRetries = value
				} else if strings.Contains(diskItem, "Write Retries") {
					data.WriteRequests = value
				} else if strings.Contains(diskItem, "Remapped Sectors") {
					data.RemappedSectors = value
				} else if strings.Contains(diskItem, "Number of Reads") {
					data.NumberOfReads = value
				} else if strings.Contains(diskItem, "Number of Writes") {
					data.NumberOfWrites = value
				} else if strings.Contains(diskItem, "Number of Luns") {
					data.NumberOfLuns = value
				} else if strings.Contains(diskItem, "Raid Group ID") {
					data.RaidGroupID = value
				} else if strings.Contains(diskItem, "Clariion Part Number") {
					data.ClariionPartNumber = value
				} else if strings.Contains(diskItem, "Request Service Time") {
					data.RequestServiceTime = value
				} else if strings.Contains(diskItem, "Read Requests") {
					data.ReadRequests = value
				} else if strings.Contains(diskItem, "Write Requests") {
					data.WriteRequests = value
				} else if strings.Contains(diskItem, "Kbytes Read") {
					data.KbytesRead = value
				} else if strings.Contains(diskItem, "Kbytes Written") {
					data.KbytesWritten = value
				} else if strings.Contains(diskItem, "Stripe Boundary Crossing") {
					data.StripeBoundaryCrossing = value
				} else if strings.Contains(diskItem, "Drive Type") {
					data.DriveType = value
				} else if strings.Contains(diskItem, "Clariion TLA Part Number") {
					data.ClariionTLAPartNumber = value
				} else if strings.Contains(diskItem, "User Capacity") {
					data.UserCapacity = value
				} else if strings.Contains(diskItem, "Idle Ticks") {
					data.IdleTicks = value
				} else if strings.Contains(diskItem, "Busy Ticks") {
					data.BusyTicks = value
				} else if strings.Contains(diskItem, "Current Speed") {
					data.CurrentSpeed = value
				} else if strings.Contains(diskItem, "Maximum Speed") {
					data.MaximumSpeed = value
				}
			}
			if data.Name != "" {
				disk.WithLabelValues(
					data.Name,
					data.VendorId,
					data.ProductId,
					data.ProductRevision,
					data.Lun,
					data.Type,
					data.State,
					data.HotSpare,
					data.PrctRebuilt,
					data.PrctBound,
					data.SerialNumber,
					data.Sectors,
					data.Capacity,
					data.Private,
					data.BindSignature,
					data.HardReadErrors,
					data.HardWriteErrors,
					data.SoftReadErrors,
					data.SoftWriteErrors,
					data.ReadRetries,
					data.WriteRetries,
					data.RemappedSectors,
					data.NumberOfReads,
					data.NumberOfWrites,
					data.NumberOfLuns,
					data.RaidGroupID,
					data.ClariionPartNumber,
					data.RequestServiceTime,
					data.ReadRequests,
					data.WriteRequests,
					data.KbytesRead,
					data.KbytesWritten,
					data.StripeBoundaryCrossing,
					data.DriveType,
					data.ClariionTLAPartNumber,
					data.UserCapacity,
					data.IdleTicks,
					data.BusyTicks,
					data.CurrentSpeed,
					data.MaximumSpeed,
				).Set(utils.DiskStateToFloat(data.State))
			}
		}
		time.Sleep(60 * time.Second)
	}
}
